package com.koron.standard.patrol.excel;

import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.util.ListUtils;
import com.koron.common.core.business.common.entity.TOrderNoMax;
import com.koron.common.core.business.common.service.TOrderNoMaxService;
import com.koron.common.core.config.ThreadLocalContext;
import com.koron.standard.patrol.bean.excel.PatrolExcel;
import com.koron.standard.patrol.bean.po.Patrol;
import com.koron.standard.patrol.bean.po.PatrolCheck;
import com.koron.standard.patrol.bean.po.PatrolRecord;
import com.koron.standard.patrol.service.PatrolCheckService;
import com.koron.standard.patrol.service.PatrolRecordService;
import com.koron.standard.patrol.service.PatrolService;
import com.koron.standard.utils.StandardCodeTools;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 针对巡视标准数据
 * @author jzp
 * @since 2022/5/16
 */
@Slf4j
public class YCPatrolExcelListener extends AnalysisEventListener<PatrolExcel> {
    private static final int BATCH_COUNT = 100;

    private String prePatrolId;
    private Integer preRowIndex;
    PatrolCheck checkRun;
    PatrolCheck checkNaRun;

    /**
     * 缓存的数据
     */
    private final List<Patrol> patrolList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
    private List<PatrolCheck> patrolCheckList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
    private List<PatrolRecord> patrolRecordList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);

    private final PatrolService patrolService;
    private final PatrolCheckService patrolCheckService;
    private final PatrolRecordService patrolRecordService;
    private final TOrderNoMaxService tOrderNoMaxService;

    public YCPatrolExcelListener(PatrolService patrolService, PatrolCheckService patrolCheckService, PatrolRecordService patrolRecordService, TOrderNoMaxService tOrderNoMaxService){
        this.patrolService = patrolService;
        this.patrolCheckService = patrolCheckService;
        this.patrolRecordService = patrolRecordService;
        this.tOrderNoMaxService = tOrderNoMaxService;
    }

    @Override
    public void invoke(PatrolExcel data, AnalysisContext context) {
        Integer rowIndex = context.readRowHolder().getRowIndex();
        // 如果分类编码和名称不为空，则创建一条设备分类数据
        if (StrUtil.isNotEmpty(data.getTypeId()) && StrUtil.isNotEmpty(data.getName())) {
            Patrol patrol = data.buildPatrol();
            patrolList.add(patrol);
            prePatrolId = patrol.getId();
            preRowIndex = rowIndex;
        }

        // // 如果检查项名称不为空。则创建检查项
        if (StrUtil.isNotEmpty(data.getCheckName())) {
            checkRun = new PatrolCheck();
            checkRun.setPatrolId(prePatrolId);
            checkRun.setStatus(0);
            checkRun.setName(data.getCheckName());
            checkRun.setContent(data.getCheckContent());
            checkRun.setSort(rowIndex - preRowIndex);
            patrolCheckList.add(checkRun);

            checkNaRun = new PatrolCheck();
            checkNaRun.setPatrolId(prePatrolId);
            checkNaRun.setStatus(1);
            checkNaRun.setName(data.getCheckName());
            checkNaRun.setContent(data.getCheckContent());
            checkNaRun.setSort(rowIndex - preRowIndex);
            patrolCheckList.add(checkNaRun);
        }else {
            checkRun.setContent(checkRun.getContent()+"\n"+data.getCheckContent());
            checkNaRun.setContent(checkNaRun.getContent()+"\n"+data.getCheckContent());
        }

        // 达到BATCH_COUNT了，需要去存储一次数据库，防止数据几万条数据在内存，容易OOM
        if (patrolCheckList.size() >= BATCH_COUNT) {
            savePatrolCheck();
            // 存储完成清理 list
            patrolCheckList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
        }

        // // 如果记录项名称不为空。则创建数据记录项
        // if (StrUtil.isNotEmpty(data.getRecordName())) {
        //     PatrolRecord record = data.buildPatrolRecord(prePatrolId, rowIndex - preRowIndex);
        //     patrolRecordList.add(record);
        //     // 达到BATCH_COUNT了，需要去存储一次数据库，防止数据几万条数据在内存，容易OOM
        //     if (patrolRecordList.size() >= BATCH_COUNT) {
        //         savePatrolRecord();
        //         // 存储完成清理 list
        //         patrolRecordList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
        //     }
        // }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        savePatrol();
        savePatrolCheck();
        // savePatrolRecord();
        log.info("所有数据解析完成！");
    }

    private void savePatrol() {
        if (patrolList.size() == 0) {
            return;
        }
        // 设置code, appid, sort
        // 1.1 获取当天最大编码
        TOrderNoMax maxNo = tOrderNoMaxService.peekNoMax(StandardCodeTools.patrolPrefix, null, patrolList.size());
        String prifix = StandardCodeTools.patrolPrefix + maxNo.getDate();
        AtomicInteger atomicInteger = new AtomicInteger(maxNo.getMaxValue()-patrolList.size());
        // 1.2 获取水司id
        String appId = ThreadLocalContext.get().getAppId();

        for (Patrol patrol : patrolList) {
            patrol.setCode(prifix + String.format("%0" + 4 + "d", atomicInteger.getAndIncrement()));
            patrol.setAppid(appId);
        }
        log.info("{}条数据，开始存储数据库！", patrolList.size());
        patrolService.saveBatch(patrolList);
        log.info("存储数据库成功！");
    }

    private void savePatrolCheck() {
        log.info("{}条数据，开始存储数据库！", patrolCheckList.size());
        patrolCheckService.saveBatch(patrolCheckList);
        log.info("存储数据库成功！");
    }

    private void savePatrolRecord() {
        log.info("{}条数据，开始存储数据库！", patrolRecordList.size());
        patrolRecordService.saveBatch(patrolRecordList);
        log.info("存储数据库成功！");
    }

}
